#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
置信度评估机制模块
实现对视频编码分析结果的置信度评估功能，考虑多种因素计算更准确的置信度值

T3-06 置信度评估机制
输入：合并后的结果
输出：带置信度的结果
依赖：T3-05 结果合并与冲突处理
"""

import logging
from typing import Dict, Any, List, Optional
from datetime import datetime
import copy

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
)
logger = logging.getLogger(__name__)


class ConfidenceEvaluator:
    """
    置信度评估器类
    负责评估各字段分析结果的置信度，并计算整体置信度
    """
    
    # 不同字段类型的权重配置
    FIELD_TYPE_WEIGHTS = {
        "scene_setting": 0.85,          # 场景设定权重
        "theme_type": 0.9,              # 主题类型权重
        "emotional_tendency": 0.8,      # 情感倾向权重
        "content_labels": 0.75,         # 内容标签权重
        "custom_fields": 0.7,           # 自定义字段权重
    }
    
    # 来源可信度权重
    SOURCE_RELIABILITY_WEIGHTS = {
        "vision": 0.7,                  # 视觉分析可信度
        "text": 0.8,                    # 文本分析可信度
        "merged": 0.85,                 # 合并结果可信度
        "conflict_resolved": 0.8,       # 冲突解决后可信度
    }
    
    # 置信度阈值定义
    CONFIDENCE_THRESHOLDS = {
        "high": 85,                     # 高置信度阈值
        "medium": 60,                   # 中等置信度阈值
        "low": 30,                      # 低置信度阈值
    }
    
    def __init__(self):
        """
        初始化置信度评估器
        """
        logger.info("置信度评估器初始化")
    
    def evaluate_confidence(self, merged_result: Dict[str, Any]) -> Dict[str, Any]:
        """
        评估合并结果的置信度
        
        Args:
            merged_result: 合并后的分析结果
            
        Returns:
            Dict[str, Any]: 包含详细置信度评估的结果
        """
        if not merged_result or "encoding_categories" not in merged_result:
            logger.error("无效的合并结果输入")
            return merged_result
        
        # 创建结果副本以避免修改原始数据
        evaluated_result = copy.deepcopy(merged_result)
        
        # 1. 评估每个字段的置信度
        self._evaluate_field_confidences(evaluated_result)
        
        # 2. 计算新的整体置信度
        self._calculate_overall_confidence(evaluated_result)
        
        # 3. 添加置信度分析信息
        self._add_confidence_analysis(evaluated_result)
        
        # 4. 标记低置信度字段
        self._mark_low_confidence_fields(evaluated_result)
        
        # 5. 添加置信度时间戳
        evaluated_result["confidence_evaluation_time"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        logger.info(f"置信度评估完成，整体置信度: {evaluated_result.get('overall_confidence', 0)}")
        return evaluated_result
    
    def _evaluate_field_confidences(self, result: Dict[str, Any]) -> None:
        """
        评估每个字段的置信度，考虑多种因素进行调整
        
        Args:
            result: 分析结果
        """
        encoding_categories = result.get("encoding_categories", {})
        
        for field_key, field_data in encoding_categories.items():
            if not isinstance(field_data, dict):
                continue
            
            # 获取原始置信度
            original_confidence = field_data.get("confidence", 0)
            adjusted_confidence = original_confidence
            
            # 考虑字段类型权重
            field_type = self._determine_field_type(field_key)
            type_weight = self.FIELD_TYPE_WEIGHTS.get(field_type, 0.75)
            
            # 考虑来源可信度
            source = field_data.get("source", "unknown")
            source_reliability = self.SOURCE_RELIABILITY_WEIGHTS.get(source, 0.7)
            
            # 检查是否有冲突解决信息
            has_conflict_resolved = field_data.get("conflict_resolved", False)
            
            # 计算调整后的置信度
            if has_conflict_resolved:
                # 冲突解决后的置信度计算
                conflict_info = field_data.get("conflict_info", {})
                conflict_strategy = conflict_info.get("resolution_strategy", "")
                
                if conflict_strategy == "confidence_based":
                    # 基于置信度的冲突解决通常更可靠
                    adjusted_confidence = min(100, int(adjusted_confidence * 1.05))
                else:
                    # 其他解决策略可能需要适当降低置信度
                    adjusted_confidence = int(adjusted_confidence * 0.95)
            
            # 应用字段类型和来源权重
            adjusted_confidence = int(adjusted_confidence * type_weight * source_reliability)
            
            # 确保置信度在合理范围内
            adjusted_confidence = max(0, min(100, adjusted_confidence))
            
            # 记录置信度调整信息
            field_data["original_confidence"] = original_confidence
            field_data["adjusted_confidence"] = adjusted_confidence
            field_data["confidence_adjustment_reason"] = self._generate_adjustment_reason(
                field_type, source, has_conflict_resolved
            )
            
            # 设置最终置信度
            field_data["confidence"] = adjusted_confidence
    
    def _calculate_overall_confidence(self, result: Dict[str, Any]) -> None:
        """
        计算整体置信度，考虑字段类型权重和字段重要性
        
        Args:
            result: 分析结果
        """
        encoding_categories = result.get("encoding_categories", {})
        weighted_confidences = []
        total_weight = 0
        
        # 收集加权置信度
        for field_key, field_data in encoding_categories.items():
            if isinstance(field_data, dict) and "confidence" in field_data:
                field_type = self._determine_field_type(field_key)
                weight = self.FIELD_TYPE_WEIGHTS.get(field_type, 0.75)
                confidence = field_data["confidence"]
                
                weighted_confidences.append(confidence * weight)
                total_weight += weight
        
        # 计算加权平均置信度
        if weighted_confidences and total_weight > 0:
            new_overall_confidence = int(sum(weighted_confidences) / total_weight)
            
            # 记录原始整体置信度
            if "original_overall_confidence" not in result:
                result["original_overall_confidence"] = result.get("overall_confidence", 0)
            
            # 更新整体置信度
            result["overall_confidence"] = new_overall_confidence
            result["confidence_change"] = new_overall_confidence - result.get("original_overall_confidence", 0)
            result["confidence_calculation_method"] = "weighted_average"
            result["confidence_field_count"] = len(weighted_confidences)
    
    def _add_confidence_analysis(self, result: Dict[str, Any]) -> None:
        """
        添加置信度分析信息
        
        Args:
            result: 分析结果
        """
        encoding_categories = result.get("encoding_categories", {})
        confidence_stats = {
            "high_confidence_fields": [],
            "medium_confidence_fields": [],
            "low_confidence_fields": [],
            "field_confidence_average": 0,
            "field_confidence_min": 100,
            "field_confidence_max": 0,
        }
        
        confidences = []
        
        # 分析字段置信度分布
        for field_key, field_data in encoding_categories.items():
            if isinstance(field_data, dict) and "confidence" in field_data:
                confidence = field_data["confidence"]
                field_name = field_data.get("name", field_key)
                confidences.append(confidence)
                
                # 分类字段
                if confidence >= self.CONFIDENCE_THRESHOLDS["high"]:
                    confidence_stats["high_confidence_fields"].append({
                        "name": field_name,
                        "key": field_key,
                        "confidence": confidence
                    })
                elif confidence >= self.CONFIDENCE_THRESHOLDS["medium"]:
                    confidence_stats["medium_confidence_fields"].append({
                        "name": field_name,
                        "key": field_key,
                        "confidence": confidence
                    })
                else:
                    confidence_stats["low_confidence_fields"].append({
                        "name": field_name,
                        "key": field_key,
                        "confidence": confidence
                    })
        
        # 计算统计信息
        if confidences:
            confidence_stats["field_confidence_average"] = int(sum(confidences) / len(confidences))
            confidence_stats["field_confidence_min"] = min(confidences)
            confidence_stats["field_confidence_max"] = max(confidences)
        
        # 添加到结果中
        result["confidence_analysis"] = confidence_stats
        
        # 评估整体分析质量
        result["analysis_quality"] = self._evaluate_analysis_quality(confidence_stats)
    
    def _mark_low_confidence_fields(self, result: Dict[str, Any]) -> None:
        """
        标记低置信度字段并提供改进建议
        
        Args:
            result: 分析结果
        """
        low_confidence_threshold = self.CONFIDENCE_THRESHOLDS["medium"]
        encoding_categories = result.get("encoding_categories", {})
        low_confidence_fields = []
        
        for field_key, field_data in encoding_categories.items():
            if isinstance(field_data, dict) and "confidence" in field_data:
                confidence = field_data["confidence"]
                if confidence < low_confidence_threshold:
                    field_name = field_data.get("name", field_key)
                    improvement_suggestion = self._generate_improvement_suggestion(
                        field_key, confidence, field_data.get("source", "unknown")
                    )
                    
                    low_confidence_fields.append({
                        "name": field_name,
                        "key": field_key,
                        "confidence": confidence,
                        "source": field_data.get("source", "unknown"),
                        "improvement_suggestion": improvement_suggestion
                    })
        
        if low_confidence_fields:
            result["low_confidence_fields"] = low_confidence_fields
            result["requires_review"] = True
        else:
            result["requires_review"] = False
    
    def _determine_field_type(self, field_key: str) -> str:
        """
        确定字段类型
        
        Args:
            field_key: 字段键名
            
        Returns:
            str: 字段类型
        """
        if field_key in self.FIELD_TYPE_WEIGHTS:
            return field_key
        elif field_key.startswith("custom_"):
            return "custom_fields"
        else:
            # 默认类型
            return "custom_fields"
    
    def _generate_adjustment_reason(self, field_type: str, source: str, has_conflict_resolved: bool) -> str:
        """
        生成置信度调整原因
        
        Args:
            field_type: 字段类型
            source: 数据源
            has_conflict_resolved: 是否解决过冲突
            
        Returns:
            str: 调整原因
        """
        reasons = []
        
        if field_type in self.FIELD_TYPE_WEIGHTS:
            reasons.append(f"字段类型权重调整({field_type})")
        
        if source in self.SOURCE_RELIABILITY_WEIGHTS:
            reasons.append(f"来源可信度调整({source})")
        
        if has_conflict_resolved:
            reasons.append("冲突解决后调整")
        
        return "; ".join(reasons) if reasons else "默认置信度"
    
    def _generate_improvement_suggestion(self, field_key: str, confidence: int, source: str) -> str:
        """
        为低置信度字段生成改进建议
        
        Args:
            field_key: 字段键名
            confidence: 置信度值
            source: 数据源
            
        Returns:
            str: 改进建议
        """
        suggestions = {
            "scene_setting": "建议增加场景识别样本或调整场景分类模型参数",
            "theme_type": "建议使用更精确的主题分类算法或增加文本分析权重",
            "emotional_tendency": "建议结合音频分析和文本情感分析以提高准确性",
            "content_labels": "建议优化关键词提取算法或增加标签训练样本",
            "custom_fields": "建议调整自定义字段的提取规则或增加验证逻辑",
        }
        
        field_type = self._determine_field_type(field_key)
        
        # 基于来源提供特定建议
        source_suggestion = ""
        if source == "vision":
            source_suggestion = "(视觉分析)建议检查视频质量或增加视频分析模型精度"
        elif source == "text":
            source_suggestion = "(文本分析)建议优化文本提取或增强NLP模型能力"
        elif source == "merged":
            source_suggestion = "(合并结果)建议调整合并策略或权重配置"
        
        base_suggestion = suggestions.get(field_type, "建议重新检查该字段的分析逻辑")
        
        return f"{base_suggestion} {source_suggestion}"
    
    def _evaluate_analysis_quality(self, confidence_stats: Dict[str, Any]) -> str:
        """
        评估整体分析质量
        
        Args:
            confidence_stats: 置信度统计信息
            
        Returns:
            str: 分析质量等级
        """
        high_count = len(confidence_stats["high_confidence_fields"])
        medium_count = len(confidence_stats["medium_confidence_fields"])
        low_count = len(confidence_stats["low_confidence_fields"])
        total_count = high_count + medium_count + low_count
        
        if total_count == 0:
            return "unknown"
        
        # 计算高质量字段比例
        high_ratio = high_count / total_count
        low_ratio = low_count / total_count
        
        if high_ratio >= 0.7 and low_ratio == 0:
            return "excellent"
        elif high_ratio >= 0.5 and low_ratio < 0.2:
            return "good"
        elif high_ratio >= 0.3 and low_ratio < 0.4:
            return "fair"
        else:
            return "poor"


# 单例模式实现
_confidence_evaluator_instance = None

def get_confidence_evaluator() -> ConfidenceEvaluator:
    """
    获取置信度评估器单例实例
    
    Returns:
        ConfidenceEvaluator: 置信度评估器实例
    """
    global _confidence_evaluator_instance
    if _confidence_evaluator_instance is None:
        _confidence_evaluator_instance = ConfidenceEvaluator()
    return _confidence_evaluator_instance


# 测试代码
if __name__ == "__main__":
    print("置信度评估器测试")
    
    # 创建测试数据
    test_merged_result = {
        "status": "success",
        "video_id": "test_video_001",
        "analysis_time": "2023-07-20 10:00:00",
        "overall_confidence": 75,
        "encoding_categories": {
            "scene_setting": {
                "name": "场景设定",
                "option": "校园场景",
                "confidence": 90,
                "source": "vision",
                "timestamp": "2023-07-20 10:00:00"
            },
            "theme_type": {
                "name": "主题类型",
                "option": "学习分享",
                "confidence": 85,
                "source": "merged",
                "timestamp": "2023-07-20 10:05:00",
                "conflict_resolved": True,
                "conflict_info": {
                    "resolution_strategy": "confidence_based"
                }
            },
            "emotional_tendency": {
                "name": "视频情感倾向",
                "option": "积极向上",
                "confidence": 90,
                "source": "text",
                "timestamp": "2023-07-20 10:05:00"
            },
            "content_labels": {
                "name": "内容标签",
                "option": "学习方法, 时间管理",
                "confidence": 88,
                "source": "text",
                "timestamp": "2023-07-20 10:05:00"
            }
        }
    }
    
    # 创建评估器实例
    evaluator = ConfidenceEvaluator()
    
    # 执行置信度评估
    evaluated_result = evaluator.evaluate_confidence(test_merged_result)
    
    # 打印评估结果
    import json
    print("\n置信度评估结果:")
    print(json.dumps(evaluated_result, ensure_ascii=False, indent=2))
    
    print("\n置信度评估器测试完成！")